using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Dragoon.BreakIt.View
{
    interface IPanelContentProvider
    {
        Menu Menu { get; }
        SpriteFont MenuFont { get; }
        Texture2D MenuBackdrop { get;}
    }

    class KeyPressHandler
    {
        readonly Keys[] _keysRecognised;
        private Keys _activeKey;

        internal KeyPressHandler(Keys[] keysToRecognise)
        {
            _keysRecognised = keysToRecognise;
        }


        public Keys GetActiveKey()
        {
            KeyboardState s = Keyboard.GetState();
            if (s.IsKeyUp(_activeKey))
                _activeKey = Keys.None;
            foreach (Keys k in _keysRecognised)
                if (s.IsKeyDown(k) && _activeKey != k)
                {
                    _activeKey = k;
                    return k;
                }
            return Keys.None;
        }
    }

    class MenuPanel : DrawableGameComponent
    {
        private const int BORDER_SIZE = 50;
        private const int LINE_SEPERATION = 5;


        private readonly IPanelContentProvider _provider;
        private SpriteBatch _batch;
        private Rectangle _windowRect;
        private int _itemHeight, _fontHeight;
        private Menu _menu;
        private KeyPressHandler _keyPress;

        public MenuPanel(Game game, IPanelContentProvider provider)
            : base(game)
        {
            _provider = provider;
            _keyPress = new KeyPressHandler(
                        new Keys[] { Keys.Up, Keys.Down, Keys.Enter, Keys.Escape });
        }


        int GetLongestString()
        {
            int maxLength = 0;
            foreach (MenuItem i in _menu.Items)
                maxLength = (int) Math.Max(_provider.MenuFont.MeasureString(i.Text).X, maxLength);
            return maxLength;
        }


        public override void Update(GameTime time)
        {
            if (_provider.Menu != _menu)
            {
                _menu = _provider.Menu;
                if (_menu == null)
                    Visible = false;
                else
                {
                    Visible = true;
                    int width = GetLongestString() + BORDER_SIZE * 2;
                    _fontHeight = (int) _provider.MenuFont.MeasureString("O").X;
                    _itemHeight = _fontHeight + LINE_SEPERATION;
                    int height = (_menu.Count + 1) * _itemHeight + BORDER_SIZE * 2;
                    _windowRect = new Rectangle(Game.Window.ClientBounds.Width / 2 - width / 2,
                                                Game.Window.ClientBounds.Height / 2 - height / 2,
                                                width, height);
                }
            }
            else if (_menu != null)
            {
                switch (_keyPress.GetActiveKey())
                {
                    case Keys.Up:
                        _menu.SelectPrevious();
                        break;
                    case Keys.Down:
                        _menu.SelectNext();
                        break;
                    case Keys.Escape:
                        _menu.Cancel(time);
                        break;
                    case Keys.Enter:
                    case Keys.Space:
                        _menu.Close(time);
                        break;
                }
            }
        }


        override public void Draw(GameTime gameTime)
        {
            if (_menu == null)
                return; // nothing to draw
            if (_batch == null)
                _batch = new SpriteBatch(GraphicsDevice);
            _batch.Begin();
            _batch.Draw(_provider.MenuBackdrop, _windowRect, Color.White);
            Vector2 textLocation =
                new Vector2(_windowRect.Left + _windowRect.Width/2,
                    _windowRect.Top + BORDER_SIZE + _fontHeight);
            Color textColor;
            foreach (MenuItem i in _menu.Items)
            {
                if (i.IsSelected)
                    textColor = Color.Red;
                else 
                    textColor = Color.Blue;
                float textWidthDiv2 = _provider.MenuFont.MeasureString(i.Text).X / 2f;
                Vector2 pos = new Vector2(textLocation.X - textWidthDiv2, textLocation.Y); 
                _batch.DrawString(_provider.MenuFont, i.Text, pos, textColor);
                textLocation.Y += _itemHeight;
            }
            _batch.End();

        }

    }
}
